package com.quad.innovators.salesease.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.quad.innovators.salesease.common.result.PageResultBean;
import com.quad.innovators.salesease.common.utils.SecurityUtils;
import com.quad.innovators.salesease.common.utils.SmUtils;
import com.quad.innovators.salesease.common.utils.SystemCodeUtils;
import com.quad.innovators.salesease.constants.SecurityConstants;
import com.quad.innovators.salesease.constants.SystemConstants;
import com.quad.innovators.salesease.converter.SysUserConverter;
import com.quad.innovators.salesease.enums.ResultCode;
import com.quad.innovators.salesease.enums.StatusEnum;
import com.quad.innovators.salesease.enums.SystemCodeEnum;
import com.quad.innovators.salesease.exception.BusinessException;
import com.quad.innovators.salesease.mapper.SysUserMapper;
import com.quad.innovators.salesease.model.bo.SysUserBO;
import com.quad.innovators.salesease.model.bo.UserRoleBO;
import com.quad.innovators.salesease.model.common.Option;
import com.quad.innovators.salesease.model.dto.SysUserAuthInfo;
import com.quad.innovators.salesease.model.dto.SysUserExportDTO;
import com.quad.innovators.salesease.model.entity.SysRole;
import com.quad.innovators.salesease.model.entity.SysRoleMenu;
import com.quad.innovators.salesease.model.entity.SysUser;
import com.quad.innovators.salesease.model.form.SysUserForm;
import com.quad.innovators.salesease.model.query.SysUserPageQuery;
import com.quad.innovators.salesease.model.vo.SysUserInfoVO;
import com.quad.innovators.salesease.model.vo.SysUserPageVO;
import com.quad.innovators.salesease.model.vo.SysUserPasswordVO;
import com.quad.innovators.salesease.security.PermissionService;
import com.quad.innovators.salesease.service.SysRoleMenuService;
import com.quad.innovators.salesease.service.SysUserRoleService;
import com.quad.innovators.salesease.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private final SysUserRoleService sysUserRoleService;

    private final SysUserConverter sysUserConverter;

    private final SysRoleMenuService sysRoleMenuService;

    private final PermissionService permissionService;

    @Override
    public PageResultBean<SysUserPageVO> listPagedUsers(SysUserPageQuery queryParams) {
        // 参数构建
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        Page<SysUserBO> page = new Page<>(pageNum, pageSize);
        // 查询数据
        Page<SysUserBO> userPage = this.baseMapper.listPagedUsers(page, queryParams);
        // 查询用户的角色
        List<String> userIdList = userPage.getRecords().stream().map(SysUserBO::getUserCode).collect(Collectors.toList());
        List<UserRoleBO> userRoleBOS = sysUserRoleService.selectRoleByUserIds(userIdList);
        Map<String, Optional<UserRoleBO>> userRoleMaps = userRoleBOS.stream().collect(Collectors.groupingBy(UserRoleBO::getUserCode, Collectors.reducing((first, second) -> second)));
        for (SysUserBO record : userPage.getRecords()) {
            if(userRoleMaps.containsKey(record.getUserCode()) && userRoleMaps.get(record.getUserCode()).isPresent()) {
                record.setRoleNames(userRoleMaps.get(record.getUserCode()).get().getRoleName());
            }
        }
        // 实体转换
        return sysUserConverter.toPageVo(userPage);
    }


    @Override
    public SysUserForm getUserFormData(String userCode) {
        SysUserForm userFormData = this.baseMapper.getUserFormData(userCode);
        List<UserRoleBO> userRoleBOS = this.sysUserRoleService.selectRoleByUserIds(Collections.singletonList(userFormData.getUserCode()));
        if(CollectionUtil.isNotEmpty(userRoleBOS)) {
            userFormData.setRoleIds(Arrays.stream(userRoleBOS.get(0).getRoleCodes().split(",")).toList());
        }else{
            userFormData.setRoleIds(new ArrayList<>());
        }
        return userFormData;
    }


    @Override
    public boolean saveUser(SysUserForm userForm) {
        String username = userForm.getUsername();
        String telephone = userForm.getTelephone();
        long count = this.count(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username)
                .or()
                .eq(SysUser::getTelephone, telephone));
        Assert.isTrue(count == 0, "用户名或手机号已存在");

        // 实体转换 form->entity
        SysUser entity = sysUserConverter.toEntity(userForm);
        entity.setUserCode(SystemCodeUtils.getCode(SystemCodeEnum.USER));
        // 设置默认加密密码
        String defaultPassword = "Aa" + telephone.substring(5);
        String defaultEncryptPwd = SmUtils.sm4Encrypt(SmUtils.sm4Encrypt(SecurityConstants.FRONT_END_PASSWORD_ENCRYPT_KEY, defaultPassword));
        entity.setPassword(defaultEncryptPwd);
        // 新增用户
        boolean result = this.save(entity);
        if (result) {
            // 保存用户角色
            sysUserRoleService.saveUserRoles(entity.getUserCode(), userForm.getRoleIds());
        }
        return result;
    }


    @Override
    @Transactional
    public boolean updateUser(String userCode, SysUserForm userForm) {
        SysUser user = this.baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserCode, userCode));
        if(user == null) {
            throw BusinessException.resultCode(ResultCode.NOT_FOUND);
        }

        long count = this.count(new LambdaQueryWrapper<SysUser>()
                    .ne(SysUser::getUserCode, userCode)
                    .and(it ->  it.eq(SysUser::getUsername, userForm.getUsername())
                                .or()
                                .eq(SysUser::getTelephone, userForm.getTelephone()))
        );
        Assert.isTrue(count == 0, "员工姓名或电话号码已存在");
        // form -> entity
        SysUser entity = sysUserConverter.toEntity(userForm);
        // 修改用户
        boolean result = this.updateById(entity);
        if (result) {
            // 保存用户角色
            sysUserRoleService.saveUserRoles(entity.getUserCode(), userForm.getRoleIds());
        }
        return result;
    }

    @Override
    public boolean updateUserStatus(String userCode, Integer status) {
        SysUser user = this.baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserCode, userCode));
        if(user == null) {
            throw BusinessException.resultCode(ResultCode.NOT_FOUND);
        }
        user.setStatus(StatusEnum.getEnum(status));
        return this.updateById(user);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUsers(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
        // 逻辑删除
        List<String> ids = Arrays.stream(idsStr.split(","))
                .collect(Collectors.toList());
        return this.removeByIds(ids);

    }


    @Override
    public SysUserAuthInfo getUserAuthInfo(String telephone) {
        SysUserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(telephone);
        if (userAuthInfo != null) {
            Set<String> roles = userAuthInfo.getRoles();
            if (CollectionUtil.isNotEmpty(roles)) {
                List<SysRoleMenu> perms = sysRoleMenuService.getRoleMenusByRoleCodes(roles);
                userAuthInfo.setPerms(perms);
            }
        }
        return userAuthInfo;
    }


    @Override
    public List<SysUserExportDTO> listExportUsers(SysUserPageQuery queryParams) {
        List<SysUserExportDTO> sysUserExportDTOS = this.baseMapper.listExportUsers(queryParams);
        // 查询用户的角色
        List<String> userIdList = sysUserExportDTOS.stream().map(SysUserExportDTO::getUserCode).collect(Collectors.toList());
        List<UserRoleBO> userRoleBOS = sysUserRoleService.selectRoleByUserIds(userIdList);
        Map<String, Optional<UserRoleBO>> userRoleMaps = userRoleBOS.stream().collect(Collectors.groupingBy(UserRoleBO::getUserCode, Collectors.reducing((first, second) -> second)));
        for (SysUserExportDTO record : sysUserExportDTOS) {
            if(userRoleMaps.containsKey(record.getUserCode()) && userRoleMaps.get(record.getUserCode()).isPresent()) {
                record.setRoleName(userRoleMaps.get(record.getUserCode()).get().getRoleName());
            }
        }
        return sysUserExportDTOS;
    }


    @Override
    public SysUserInfoVO getCurrentUserInfo() {

        String username = SecurityUtils.getUsername();

        // 获取登录用户基础信息
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username)
                .select(
                        SysUser::getId,
                        SysUser::getUsername
                )
        );
        // entity->VO
        SysUserInfoVO userInfoVO = sysUserConverter.toUserInfoVo(user);

        // 用户角色集合
        Set<String> roles = SecurityUtils.getRoles();
        userInfoVO.setRoles(roles);

        // 用户权限集合
        if (CollectionUtil.isNotEmpty(roles)) {
            Set<String> perms = permissionService.getRolePermsFormCache(roles);
            userInfoVO.setPerms(perms);
        }
        return userInfoVO;
    }

    @Override
    public SysUserPasswordVO getUserPassword(String userCode) {
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserCode, userCode)
                .select(
                        SysUser::getId,
                        SysUser::getPassword
                )
        );
        if(user != null){
            return new SysUserPasswordVO(SmUtils.sm4Decrypt(user.getPassword()));
        }
        throw  BusinessException.resultCode(ResultCode.NOT_FOUND);
    }


    @Override
    public boolean resetPassword(String userCode, String password) {
        return this.update(new LambdaUpdateWrapper<SysUser>()
                .eq(SysUser::getUserCode, userCode)
                .set(SysUser::getPassword, SmUtils.sm4Encrypt(password))
        );
    }

    @Override
    public List<Option<String>> listRoleOptions() {
        // 查询数据
        List<SysUser> userList = this.list(new LambdaQueryWrapper<SysUser>()
                        .eq(SysUser::getStatus, 1)
                .select(SysUser::getUserCode, SysUser::getUsername)
                .orderByDesc(SysUser::getUpdateTime)
        );
        // 实体转换
        return sysUserConverter.entities2Options(userList);
    }

}
